home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / SAT 2.3.7 / Demos / Demo ƒ / SAT Invaders demo ƒ / main.p < prev    next >
Encoding:
Text File  |  1995-09-12  |  10.8 KB  |  354 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== SATInvaders main unit ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { SATInvaders is a very simple game demonstrating how to use the Sprite Animation}
  10. { Toolkit. It is intended as a minimal demonstration, without many features and options}
  11. { that the other sample program, HeartQuest, has. No high scores or even score, only}
  12. { one life, doesn't save settings, only one kind of enemy, no special effects like explosions}
  13. { etc. However, it is still a full Mac application with menus and event handling (using}
  14. {TransSkel).}
  15.  
  16. {In SAT version 1, this was the "minimal" demo. There are now several even more}
  17. {"minimal" demos, esp. the Tutorial and SATminimal.}
  18.  
  19. program SATInvaders;
  20.  
  21.     uses
  22. {$IFC UNDEFINED THINK_PASCAL}
  23.         Types, QuickDraw, Menus, ToolUtils, Resources, {}
  24.         TransSkel, 
  25. {$ELSEC}
  26.         TransSkel, 
  27. {$ENDC}
  28.         SAT, GameGlobals, SoundConst, StarField, sPlayer, sEnemy, sShot, sMissile;
  29.  
  30.     var
  31.         soundFlag, plotFastFlag, starFieldFlag: Boolean;
  32.  
  33. { -------------------------------------------------------------------- }
  34. {                                Game driver procedures                                }
  35. { -------------------------------------------------------------------- }
  36.  
  37. { Setup a new level. This is called when the game starts and at each new level.}
  38.     procedure SetupLevel (level: integer);
  39.         var
  40.             i, j: integer;
  41.             sp: SpritePtr;
  42.     begin { SetupLevel }
  43.  
  44. { Clear the Sprite list! Note that this leaves the images "dead" on the screen,}
  45. { but we will soon erase them. }
  46.         while gSAT.sRoot <> nil do
  47.             SATKillSprite(gSAT.sRoot);
  48.  
  49.         missileCount := 0; { count variable in mMissile }
  50.  
  51. { Create all the enemy sprites for the level, depending on the level number. }
  52.         for i := 0 to (level + 1) do
  53.             for j := 0 to (level div 2) + 1 do
  54.                 sp := SATNewSprite(-3, i * 40 + 2, j * 40 - 40 * (level div 2 + 1), @SetupEnemy);
  55.  
  56. { Make the player sprite. }
  57.         sp := SATNewSprite(2, gSAT.offSizeH div 2, gSAT.offSizeV - 40, @SetupPlayer);
  58.  
  59. { Copy BackScreen to OffScreen to erase old sprites. }
  60.         CopyBits(gSAT.backScreen.port^.portbits, gSAT.offScreen.port^.portbits, gSAT.offScreen.port^.portrect, gSAT.offScreen.port^.portrect, srcCopy, nil);
  61.         SATRedraw;
  62.     end; { SetupLevel }
  63.  
  64. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  65.     procedure StartGame;
  66.     begin
  67.         level := 1;
  68.         SetupLevel(level);
  69.     end;
  70.  
  71. { Declare forward since we want to call it from MoveIt }
  72.     procedure DoFileMenu (item: integer);
  73.     forward;
  74.  
  75. { This routine is the game driver. It calls SATRun repeatedly until the game ends or is paused. }
  76. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  77.  
  78.     procedure MoveIt;
  79.         var
  80.             t: longint;
  81.             theEvent: EventRecord; { för att testa musklick }
  82.     begin
  83.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  84.  
  85. { Hide cursor and menu bar }
  86.  { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  87.         HideCursor;
  88.         SATHideMBar(gSAT.wind.port);
  89.         SATRedraw; {We must redraw the menu bar area. I'm lazy and redraw it all.}
  90.  
  91. { Main loop! Keep running until the game is paused or ends. }
  92.         while stillrunning = true do
  93.             begin
  94.                 t := TickCount; {Remember when we started the last turn through the loop.}
  95.  
  96.                 if starFieldFlag then
  97.                     DoStars;
  98.  
  99. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects,}
  100. { draw and erase them, sort them etc. }
  101.                 SATRun(plotFastFlag);
  102.  
  103. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  104.  
  105. {Handle the speed of the invaders. Since all move the same way, this is done globally.}
  106.                 if globalspeed.h = 0 then
  107.                     begin
  108.                         downcount := pred(downcount);
  109.                         if downcount <= 0 then
  110.                             begin
  111.                                 globalspeed.h := -lasth;
  112.                                 globalspeed.v := 0;
  113.                                 turnflag := false;
  114.                             end;
  115.                     end
  116.                 else if turnflag then
  117.                     begin
  118.                         downcount := 10;
  119.                         lasth := globalspeed.h;
  120.                         globalspeed.h := 0;
  121.                         globalspeed.v := 3;
  122.                     end;
  123.  
  124. {End of level? If so, set up a new one!}
  125.                 if not gSAT.anyMonsters then
  126.                     begin
  127.                         SATSoundShutUp;
  128.                         level := level + 1;
  129.                         SetupLevel(level);
  130.                     end; {if not anymonsters}
  131.  
  132. { Check for keys being pressed - but don't allow background processing.}
  133. { If you want background processing, either use GetNextEvent+SystemTask or WaitNextEvent (the modern call).}
  134.                 if GetOSEvent(keyDownMask, theEvent) then { keydown only }
  135.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then {Command key pressed?}
  136.                         case char(BitAnd(theEvent.message, charCodeMask)) of {With what key?}
  137.                             'q': 
  138.                                 begin {Quit!}
  139.                                     SkelWhoa;        {Tell TransSkel to quit.}
  140. { Do all the things we have to do when we leave MoveIt! }
  141.                                     SATSoundShutUp; { Dispose of sound channel }
  142.                                     FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  143.                                     ShowCursor;
  144.                                     SATShowMBar(gSAT.wind.port);
  145.                                     exit(MoveIt);
  146.                                 end;
  147.                             's': 
  148.                                 begin {Sound on/off}
  149.                                     DoFileMenu(sound);
  150.                                 end;
  151.                             otherwise
  152.                                 ; {Ignore others}
  153.                         end; { case}
  154.  
  155. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  156.                 while ((TickCount - t) < 3) do {3/60 per frame = 20 fps if possible}
  157.                     ;
  158.             end; { while stillrunning (main loop) }
  159.  
  160.         while not SATSoundDone do
  161.             SATSoundEvents; {Wait for last sound to complete}
  162.  
  163.         ShowCursor; {Balance HideCursor}
  164.         SATShowMBar(gSAT.wind.port);
  165.         FlushEvents(EveryEvent - DiskMask, 0); { To forget events, like mouse clicks etc. except disk events }
  166.  
  167.         SATReportStr('Sorry, game over.');
  168.  
  169.         SATSoundShutUp; { Dispose of sound channel }
  170.     end; { MoveIt }
  171.  
  172.     procedure GameWindUpdate;
  173.         var
  174.             watch: CursHandle;
  175.     begin
  176. {Set the cursor to wait cursor during screen depth change test. If there's no change,}
  177. {the user won't notice.}
  178.         watch := GetCursor(WatchCursor);
  179.         SetCursor(watch^^);
  180.         if SATDepthChangeTest then
  181.             begin
  182. {Do anything needed after a screen depth change. In this demo, nothing.}
  183.             end;
  184.         ReleaseResource(Handle(watch));
  185. {Set the cursor to arrow again.}
  186.         InitCursor;
  187.  
  188. {Process the update event by redrawing the window.}
  189.         SATRedraw;
  190.  
  191. {Note: SATRedraw can be replaced by drawing with CopyBits, i.e.:}
  192. {SATSetPortScreen;}
  193. {CopyBits(offScreen.port^.portBits, gSAT.wind.port^.portBits, offScreen.port^.portRect, offScreen.port^.portRect, srcCopy, nil);}
  194. {plus drawing borders. SATRedraw draws them black.}
  195.     end;
  196.  
  197. {    Process selection from File menu.}
  198.  
  199.     procedure DoFileMenu (item: integer);
  200.     begin
  201.         case item of
  202.             run: 
  203.                 begin
  204. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  205.                     if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and plotFastFlag then
  206.                         begin
  207.                             SATReportStr('Please uncheck ''Fast animation'' or set the monitor to b/w, 4-bit or 8-bit mode in the Control Panel.');
  208.                             exit(DoFileMenu);
  209.                         end;
  210.                     if SATDepthChangeTest then {Update if necessary}
  211.                         ;
  212.                     StartGame;
  213.                     ShowWindow(gSAT.wind.port);
  214.                     SelectWindow(gSAT.wind.port);
  215.                     GameWindUpdate;
  216.                     MoveIt;
  217.                 end;
  218.             sound: 
  219.                 begin
  220.                     soundFlag := not soundFlag;
  221.                     CheckItem(FileMenu, sound, soundFlag);
  222.                     if soundFlag then { Tell the sound package our settings, so we don't have to bother. }
  223.                         SATSoundOn
  224.                     else
  225.                         SATSoundOff;
  226.                 end;
  227.             fastAnimation: 
  228.                 begin
  229.                     plotFastFlag := not plotFastFlag;
  230.                     CheckItem(fileMenu, fastAnimation, plotFastFlag);
  231.                 end;
  232.             starField: 
  233.                 begin
  234.                     starFieldFlag := not starFieldFlag;
  235.                     CheckItem(fileMenu, starField, starFieldFlag);
  236.                     ToggleStarField(starFieldFlag);
  237.                 end;
  238.             quit: 
  239.                 SkelWhoa;
  240.         end;
  241.     end;
  242.  
  243.     procedure GameWindInit;
  244.     begin
  245. { Tell TransSkel to tell us when to update SATwind. }
  246.         if SkelWindow(gSAT.wind.port, nil, nil, @GameWindUpdate, nil, nil, nil, nil, false) then
  247.             ;
  248.  
  249. {We use SATCustomInit, so we must show the window ourselves}
  250.         ShowWindow(gSAT.wind.port);
  251.         SelectWindow(gSAT.wind.port);
  252. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  253.         SATRedraw;
  254.     end;
  255.  
  256. { -------------------------------------------------------------------- }
  257. {                        Menu handling procedures                        }
  258. { -------------------------------------------------------------------- }
  259.  
  260. {    Handle selection of "About…" item from Apple menu}
  261.  
  262.     procedure DoAbout;
  263.         var
  264.             versionString: Str255;
  265.     begin
  266.         SATGetVersion(versionString);
  267.         ParamText(versionString, '', '', '');
  268.         if Alert(aboutAlrt, nil) = 1 then
  269.             ;
  270.     end;
  271.  
  272. {    Initialize menus.  Tell TransSkel to process the Apple menu}
  273. {    automatically, and associate the proper procedures with the}
  274. {    File menu.}
  275.  
  276.     procedure SetUpMenus;
  277.     begin
  278.         SkelApple('About SAT Invaders…', @DoAbout);
  279.         fileMenu := GetMenu(fileMenuRes);
  280.         if SkelMenu(fileMenu, @DoFileMenu, nil, true) then
  281.             ;
  282. { Set the following flags so they match the menu }
  283.         soundFlag := true;
  284.         plotFastFlag := true;
  285.     end;
  286.  
  287. { Hide gamewindow on suspend, so the user can get access to disk icons etc. }
  288.  
  289.     procedure DoSuspendResume (b: boolean);
  290.     begin
  291.         if b then
  292.             begin
  293.                 ShowWindow(gSAT.wind.port);
  294.                 SelectWindow(gSAT.wind.port);
  295.             end
  296.         else
  297.             HideWindow(gSAT.wind.port)
  298.     end;
  299.  
  300.     function DoEvt (e: eventRecord): boolean;
  301.     begin
  302.         if e.what = OSevt then
  303.             begin
  304.                 if BAND(BROTL(e.message, 8), $FF) = SuspendResumeMessage then
  305.                     DoSuspendResume(BAnd(e.message, 1) <> 0);
  306.                 DoEvt := true;
  307.             end
  308.         else
  309.             DoEvt := false;
  310.     end; (* end DoEvent *)
  311.  
  312. { -------------------------------------------------------------------- }
  313. {                                    Main                                }
  314. { -------------------------------------------------------------------- }
  315.  
  316.     var
  317.         gameArea: Rect;
  318.  
  319. begin
  320.     SkelInit(6, nil);                { initialize }
  321.  
  322. { Init all the different parts of the game. }
  323.  
  324.     SetUpMenus;                        { install menu handlers }
  325.  
  326.     SetRect(gameArea, 0, 0, 512, 342);
  327. {We use SATCustomInit to cover the full screen INCLUDING menu bar area!}
  328.     SATCustomInit(129, 128, gameArea, nil, nil, true, true, true, true, true);
  329. {SATInit(129, 128, 512, 322);    {PICTs 129 and 128, width 512, height 322.}
  330.     GameWindInit;    { Install the game window (SATwind) in TransSkel and show it. }
  331.     Loadsounds;        { Preload all sound resources }
  332.  
  333. { Call the init routines for all the sprite units (generally to preload faces)!}
  334. { This must be done after SATInit! }
  335.     InitEnemy;
  336.     InitPlayer;
  337.     InitMissile;
  338.     InitShot;
  339.  
  340. {$IFC UNDEFINED THINK_PASCAL}
  341.     qd.randSeed := TickCount;    { Set the randseed to something that is random enough. }
  342. {$ELSEC}
  343.     randSeed := TickCount;    { Set the randseed to something that is random enough. }
  344. {$ENDC}
  345.  
  346.     if 0 < SATSoundInitChannels(2) then
  347.         ; {Use 2 channels}
  348.  
  349.     SkelEventHook(@DoEvt); { Handle MultiFinder-events }
  350.  
  351.     SkelMain;                    { Loop 'til Quit selected }
  352.     SkelClobber;                { Clean up }
  353.     SATSoundShutUp;            { Terminate sounds, free the sound channel. }
  354. end.